package com.insight.modules.util;

import cn.hutool.core.util.RandomUtil;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.apache.poi.ss.usermodel.Workbook;
import com.insight.common.system.util.ExcelUtilJeecg;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wangruheng
 * @title: ZipEncryUtils
 * @projectName jeecg-boot-parent
 * @description: TODO 导出加密
 * @date 2021/8/11-9:02
 */
@Slf4j
@Component
public class ZipEncryUtils {
    @Value("${jeecg.path.upload}")
    private String upload;

    /**
     * excle 导出加密方法
     * @param fileName  文件名称
     * @param response  response
     * @param workbook  excle 导出
     * @param passwd    加密密码
     * @throws Exception
     */
    public void excelEncry(String fileName, HttpServletResponse response, Workbook workbook, String passwd) throws ZipException, IOException{
        String[] split = fileName.split("\\.");
        fileName = split[0]+ "_" + System.currentTimeMillis() + "." + split[1];
        //密码参数
        ZipParameters parameters = getZipParameters(fileName,passwd);
        //zip包文件名称
        String zipFileName =fileName.substring(0,fileName.lastIndexOf('.'))+".zip";
        //zip包存放路基
        String zipFileUrl = getPoth()+zipFileName;
        System.out.println(zipFileUrl);
        ZipFile zipFile = new ZipFile(zipFileUrl);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            workbook.write(bos);
        } finally {
            try {
                bos.close();
            } catch (IOException ignored) {
                log.error("关闭流异常", e);
            }
        }
        byte[] bytes = bos.toByteArray();

        try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
            zipFile.addStream(inputStream, parameters);
        }

        File file = new File(zipFileUrl);

        // 告诉浏览器用什么软件可以打开此文件
        response.setHeader("content-Type", "multipart/form-data");
        //设置浏览器响应头对应的Content-disposition
        response.setHeader("Content-Disposition",
                "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
        //编码
        response.setCharacterEncoding("UTF-8");

        InputStream fis = new FileInputStream(file);
        OutputStream os = response.getOutputStream();
        byte[] b = new byte[1024 * 1024 * 200];
        int len;
        while ((len = fis.read(b)) > 0) {
            os.write(b, 0, len);
        }
        os.flush();
        os.close();
        fis.close();
    }

    /**
     * 导出Excel导入模板
     * @param fileName    文件名称
     * @param response
     * @param inputStream 导出流
     * @param passwd      密码
     */

    public void excelTemplate(String fileName, HttpServletResponse response,InputStream inputStream, String passwd) throws ZipException, IOException {
        //密码参数
        ZipParameters parameters = getZipParameters(fileName,passwd);
        //zip包文件名称
        String zipFileName =fileName.substring(0,fileName.lastIndexOf('.'))+".zip";
        //zip包存放路基
        String zipFileUrl = getPoth()+zipFileName;
        System.out.println(zipFileUrl);
        ZipFile zipFile = new ZipFile(zipFileUrl);
        zipFile.addStream(inputStream, parameters);

        File file = new File(zipFileUrl);
        // 告诉浏览器用什么软件可以打开此文件
        response.setHeader("content-Type", "multipart/form-data");
        //设置浏览器响应头对应的Content-disposition
        response.setHeader("Content-Disposition",
                "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
        //编码
        response.setCharacterEncoding("UTF-8");

        InputStream fis = new FileInputStream(file);
        OutputStream os = response.getOutputStream();
        byte[] b = new byte[1024 * 1024 * 200];
        int len;
        while ((len = fis.read(b)) > 0) {
            os.write(b, 0, len);
        }
        os.flush();
        os.close();
        fis.close();
    }

    /**
     * 加密pdf文档
     * @param pdfPath pdf存放的路径
     * @return zip 压缩包的路径
     */
    public String pdfEncry(String pdfPath, String passwd) throws IOException, ZipException {
        pdfPath = pdfPath.replaceAll("//", "/").replaceAll("\\\\", "/");
        String pdfName = pdfPath.substring(pdfPath.lastIndexOf('/') + 1);
        String zipFileUrl = getPoth() + pdfName.substring(0, pdfName.lastIndexOf('.')) + ".zip";

        ZipParameters parameters = getZipParameters(pdfName, passwd);
        File file = new File(pdfPath);
        try (InputStream inputStream = new FileInputStream(file)) {
            ZipFile zipFile = new ZipFile(zipFileUrl);
            zipFile.addStream(inputStream, parameters);
        }
        return zipFileUrl;
    }


    /**
     * 密码参数
     * @param fileName  要加密文件名称
     * @param passwd    密码
     * @return
     */
    private ZipParameters getZipParameters(String fileName ,String passwd){
        ZipParameters parameters = new ZipParameters();
        // 压缩方式
        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        // 压缩级别
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        parameters.setSourceExternalStream(true);
        parameters.setFileNameInZip(fileName);
        if (!"".equals(passwd)) {
            parameters.setEncryptFiles(true);
            // 加密方式
            parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
            parameters.setPassword(passwd.toCharArray());
        }
        return parameters;
    }

    /**
     * 获取 .zip 文件要存放的位置
     * @return
     */
    private String getPoth(){
        String filePath = upload+"/zipEncry/";
        File file = new File(filePath);
        if(!file.isDirectory()){
            file.mkdirs();
        }
        return filePath;
    }


    public void zipPwd(HttpServletResponse response, Class<?> clazz, String title, String pwd, Boolean isEncry, List<?> exportList) {
        ExportParams exportParams1 = new ExportParams();
        exportParams1.setSheetName(title);
        Map<String, Object> deptDataMap = new HashMap<>(4);
        // title的参数为ExportParams类型
        deptDataMap.put("title", exportParams1);
        // 模版导出对应得实体类型
        deptDataMap.put("entity", clazz);
        // sheet中要填充得数据
        deptDataMap.put("data", exportList);

        List<Map<String, Object>> sheetsList = new ArrayList<>();
        sheetsList.add(deptDataMap);
        // 执行方法
        Workbook workbook = null;

        workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF);

        if (isEncry == null || pwd == null){
            ExcelUtilJeecg.downLoadExcel(title+".xls",response,workbook);
            return;
        }
        if(isEncry){
            try {
                this.excelEncry(title+".xls",response,workbook,pwd);
            } catch (ZipException e) {
                e.printStackTrace();
            } catch (IOException e){
                e.printStackTrace();
            }
        }else{
            ExcelUtilJeecg.downLoadExcel(title+".xls",response,workbook);
        }
    }
}
